package com.atguigu.spzx.product.service.imple;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.atguigu.spzx.common.exception.GuiguException;
import com.atguigu.spzx.model.dto.h5.ProductSkuDto;
import com.atguigu.spzx.model.entity.order.OrderItem;
import com.atguigu.spzx.model.entity.product.Product;
import com.atguigu.spzx.model.entity.product.ProductDetails;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.model.vo.h5.ProductItemVo;
import com.atguigu.spzx.product.mapper.ProductDetailsMapper;
import com.atguigu.spzx.product.mapper.ProductSkuMapper;
import com.atguigu.spzx.product.service.ProductService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ProductServiceImpl implements ProductService {
    @Resource
    ProductSkuMapper productSkuMapper;
    @Resource
    ProductDetailsMapper productDetailsMapper;
    @Override
    public PageInfo<ProductSku> findByPage(Integer page, Integer limit, ProductSkuDto productSkuDto) {
        PageHelper.startPage(page,limit);
        List<ProductSku> list = productSkuMapper.findByPage(productSkuDto);
        return new PageInfo<ProductSku>(list);
    }

    @Override
    public ProductItemVo findBySkuId(Long skuId) {
//        productSkuMapper.findProductBySkuId()
        //1、查询sku
        ProductSku productSku = productSkuMapper.findSkuBySkuId(skuId);
        //2、查询product
        Product product = productSkuMapper.findProductBySpuId(productSku.getProductId());
        //3、处理product的轮播图
        String sliderUrls = product.getSliderUrls();
        List<String> sliderUrlList = null;
        if(StringUtils.hasLength(sliderUrls)){
            sliderUrlList = Arrays.asList(sliderUrls.split(","));
        }
        //[{"key":"颜色","valueList":["白色"]},{"key":"内存","valueList":["8G","12G"]}]
        //4、将product的SpecValue转为 一个个的Map存到List中
        String specValue = product.getSpecValue();
        List specValueList = null;
        if(StringUtils.hasLength(specValue)){
            //将[]开始的 json数组的字符串 转为 List集合  ，json数组中每个位置的元素如果是json对象  会自动被转为Map类型
            // 如果我们为json数组中的每个位置的元素创建了自定义类型，那么可以使用 JSON.parseArray(specValue,自定义类型) 可以将json数组转为指定类型的对象集合
            specValueList = JSON.parseArray(specValue);

        }
        //5、查询商品详情图地址
        ProductDetails productDetails = productDetailsMapper.findByProductId(product.getId());
        String imageUrls = productDetails.getImageUrls();
        List<String> imageUrlList = null;
        if(StringUtils.hasLength(imageUrls)){
           imageUrlList  = Arrays.asList(imageUrls.split(","));
        }
        //6、根据productid查询所有的sku
        List<ProductSku> productSkus = productSkuMapper.findAllSkuByProductId(product.getId());
        //将所有sku的 specValue值 和id映射存到一个Map中
        Map<String, Long> map = productSkus.stream()
                //将每个productSku的 skuSpec值作为键  它的id作为值 存到一个Map中
                .collect(Collectors.toMap(ProductSku::getSkuSpec, ProductSku::getId));


        ProductItemVo productItemVo = new ProductItemVo();
        productItemVo.setProductSku(productSku);
        productItemVo.setProduct(product);
        productItemVo.setSliderUrlList(sliderUrlList);
        productItemVo.setSpecValueList(specValueList);
        productItemVo.setDetailsImageUrlList(imageUrlList);
        productItemVo.setSkuSpecValueMap(map);


        return productItemVo;
    }

    @Override
    public ProductSku findSkuBySkuId(Long skuId) {

        return productSkuMapper.findSkuBySkuId(skuId);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<ProductSku> findProductSkus(List<OrderItem> orderItemList) {
        //可以加分布式锁+数据库字段值设置为无符号 解决超卖问题
        //不能加数据库锁：可能会锁升级或者死锁
        //1、如果orderItemList为空返回空
        if(CollectionUtils.isEmpty(orderItemList)){
            return null;
        }
        //2、根据orderItem集合 遍历 判断价格是否变动、判断库存是否足够  如果足够 更新库存
        List<Long> skuIds = orderItemList.stream().map(OrderItem::getSkuId).collect(Collectors.toList());
        List<ProductSku> productSkus = productSkuMapper.findSkusBySkuIds(skuIds);
        if(CollectionUtils.isEmpty(productSkus) || productSkus.size()!= orderItemList.size()){
            //查询商品列表 和订单项列表对应不上
            throw new GuiguException(ResultCodeEnum.UNKNOW_ERROR);
        }
        //3、验库存和价格
        //将productSku转为Map<SkuId , ProductSku>
        Map<Long, ProductSku> map = new HashMap<>();
        productSkus.forEach(productSku -> {
            map.put(productSku.getId() , productSku);
        });
        orderItemList.forEach(orderItem -> {
            //获取购物项对应的商品
            ProductSku productSku = map.get(orderItem.getSkuId());
            //判断库存
            if(productSku.getStockNum()<orderItem.getSkuNum()){
                throw new GuiguException(ResultCodeEnum.UNKNOW_ERROR);
            }
            //判断价格
            if(productSku.getSalePrice().compareTo(orderItem.getSkuPrice())!=0){
                throw new GuiguException(ResultCodeEnum.UNKNOW_ERROR);
            }
            //更新库存: 数据库product_sku表库存字段需要设置无符号约束
            boolean updateFlag = productSkuMapper
                    .updateStockNumById(productSku.getId() , orderItem.getSkuNum());
            if(!updateFlag){
                //商品减库存失败
                throw new GuiguException(ResultCodeEnum.UNKNOW_ERROR);
            }
        });

        return productSkus;
    }

    public static void main(String[] args) {
        String  str = "[{\"key\":\"颜色\",\"valueList\":[\"白色\"]},{\"key\":\"内存\",\"valueList\":[\"8G\",\"12G\"]}]";
        List list = JSON.parseArray(str);
        list.forEach(obj ->{
            System.out.println(obj.getClass().getName());
        });



    }
}
